#include <logbase.h>
// 结构体与联合体
struct PersonBaseInform;
typedef void (*setName)(struct PersonBaseInform *, const char *);

// struct msgDtStct
// {
//     int rmtKey;// remote key id
//     int msgSize;
//     char msgData[ONE_MSG_MAX_LEN]; // 8k左右有问题，>8k直接错误
// } __attribute__((packed));// gcc标准，其他地方还不好用。用#pragma
// __attribute__((packed))取消对其

#pragma pack(1) //
struct PersonBaseInform
{
    uint32_t id;
    uint8_t age;
    float height;
    uint16_t weight;
    char name[7];
    setName setNameFunc;
};
struct StudentInformStruct
{
    struct PersonBaseInform base;
    int score; // 成绩
};
struct TeachorInformStruct
{
    struct PersonBaseInform base;
    char teachObject[20]; // 授课科目
};
struct CommandInformStruct
{
    int personFlag; // 0是学生，1是老师
    union//匿名联合体， c99
    {
        struct StudentInformStruct student;
        struct TeachorInformStruct teacher;
    };
};
// 主要用于一些协议之中，根据不同命令，使用不同结构体。
// 备注：这里没有考虑大小端。如果都是小端系统、都是大端系统，没有问题。
#pragma pack()

void setStudentName(struct PersonBaseInform *studentPointor, const char *setname)
{
    if (!studentPointor)
    {
        logerrorc("");
        return;
    }
    if (!setname)
    {
        logerrorc("");
        return;
    }
    // 常用库函数。跟printf一样，sprintf使用指定格式输出到一个字符串中。snprintf是升级版，指定输出长度，防止崩溃。
    snprintf(studentPointor->name, sizeof(studentPointor->name), "%s", setname);
}

void printfPersonCommandInform(struct CommandInformStruct *cmd)
{
    if (!cmd)
    {
        logerrorc("");
        return;
    }
    if (cmd->personFlag == 0)
    {
        logdebugc("this is student inform");
        logdebugc("id=%u", cmd->student.base.id);
        logdebugc("name=%s", cmd->student.base.name);
        logdebugc("score=%d", cmd->student.score);
    }
    else if (cmd->personFlag == 1)
    {
        logdebugc("this is teachor inform");
        logdebugc("id=%u", cmd->teacher.base.id);
        logdebugc("name=%s", cmd->teacher.base.name);
        logdebugc("score=%s", cmd->teacher.teachObject);
    }
}

int main(int argc, char **argv)
{
    logdebugc("union size is max struct size:%lu", sizeof(struct CommandInformStruct));
    struct CommandInformStruct tmpcommand;
    tmpcommand.personFlag = 0;
    tmpcommand.student.base.id = 1001;
    tmpcommand.student.score = 55;
    tmpcommand.student.base.setNameFunc = setStudentName;
    tmpcommand.student.base.setNameFunc(&tmpcommand.student.base, "stud");
    printfPersonCommandInform(&tmpcommand);

    tmpcommand.personFlag = 1;
    tmpcommand.teacher.base.id = 1002;
    snprintf(tmpcommand.teacher.teachObject, sizeof(tmpcommand.teacher.teachObject), "%s", "math");
    snprintf(tmpcommand.teacher.base.name, sizeof(tmpcommand.teacher.base.name), "%s", "teac");
    printfPersonCommandInform(&tmpcommand);
    return 1;
}
